<template>
  <div class="pagination-container" :class="{ 'pagination-sm': size === 'small' }">
    <!-- 总条数信息 -->
    <div v-if="showTotal" class="pagination-total">
      共 {{ total }} 条
    </div>

    <!-- 每页条数选择器 -->
    <div v-if="showSizeChanger" class="pagination-size-changer">
      每页
      <select
        v-model="currentPageSize"
        class="pagination-select"
        @change="handleSizeChange"
      >
        <option
          v-for="size in pageSizes"
          :key="size"
          :value="size"
        >
          {{ size }} 条
        </option>
      </select>
    </div>

    <!-- 页码导航 -->
    <div class="pagination-nav">
      <!-- 首页按钮 -->
      <button
        v-if="showFirstLastPage"
        class="pagination-btn"
        :disabled="currentPage === 1 || disabled"
        @click="handleFirstPage"
      >
        <i class="fa fa-angle-double-left"></i>
      </button>

      <!-- 上一页按钮 -->
      <button
        class="pagination-btn"
        :disabled="currentPage === 1 || disabled"
        @click="handlePrevPage"
      >
        <i class="fa fa-angle-left"></i>
      </button>

      <!-- 页码列表 -->
      <div class="pagination-numbers">
        <!-- 省略号 -->
        <span
          v-if="showPrevEllipsis"
          class="pagination-ellipsis"
        >
          ...
        </span>

        <!-- 页码按钮 -->
        <button
          v-for="page in pageNumbers"
          :key="page"
          class="pagination-number"
          :class="{
            'is-active': page === currentPage,
            'is-disabled': disabled
          }"
          :disabled="disabled"
          @click="handlePageChange(page)"
        >
          {{ page }}
        </button>

        <!-- 省略号 -->
        <span
          v-if="showNextEllipsis"
          class="pagination-ellipsis"
        >
          ...
        </span>
      </div>

      <!-- 下一页按钮 -->
      <button
        class="pagination-btn"
        :disabled="currentPage === totalPages || disabled"
        @click="handleNextPage"
      >
        <i class="fa fa-angle-right"></i>
      </button>

      <!-- 末页按钮 -->
      <button
        v-if="showFirstLastPage"
        class="pagination-btn"
        :disabled="currentPage === totalPages || disabled"
        @click="handleLastPage"
      >
        <i class="fa fa-angle-double-right"></i>
      </button>
    </div>

    <!-- 跳转页码 -->
    <div v-if="showJumper" class="pagination-jumper">
      前往
      <input
        type="number"
        v-model.number="jumpPage"
        class="pagination-input"
        :min="1"
        :max="totalPages"
        :disabled="disabled"
        @keyup.enter="handleJump"
      >
      页
      <button
        class="pagination-jump-btn"
        :disabled="!jumpPage || jumpPage < 1 || jumpPage > totalPages || disabled"
        @click="handleJump"
      >
        确定
      </button>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, watch, onMounted } from 'vue';

// 定义组件的Props
const props = defineProps<{
  // 当前页码
  currentPage: number;
  // 总条数
  total: number;
  // 每页显示条数
  pageSize: number;
  // 每页显示条数选项
  pageSizes?: number[];
  // 显示的页码数量
  pageCount?: number;
  // 是否显示总条数
  showTotal?: boolean;
  // 是否显示每页条数选择器
  showSizeChanger?: boolean;
  // 是否显示跳转页码
  showJumper?: boolean;
  // 是否显示首页和末页按钮
  showFirstLastPage?: boolean;
  // 组件大小
  size?: 'default' | 'small';
  // 是否禁用
  disabled?: boolean;
}>();

// 定义组件的Emits
const emit = defineEmits<{
  // 页码变化事件
  (e: 'update:currentPage', page: number): void;
  // 每页条数变化事件
  (e: 'update:pageSize', size: number): void;
  // 页码或每页条数变化时触发
  (e: 'change', page: number, pageSize: number): void;
}>();

// 内部状态管理
const currentPageSize = ref(props.pageSize);
const jumpPage = ref(props.currentPage);

// 计算总页数
const totalPages = computed(() => {
  if (props.total <= 0) return 1;
  return Math.ceil(props.total / currentPageSize.value);
});

// 计算显示的页码列表
const pageNumbers = computed(() => {
  const pages: number[] = [];
  const count = props.pageCount || 5; // 默认显示5个页码
  const total = totalPages.value;
  const current = props.currentPage;

  // 总页数小于等于显示数量，直接显示所有页码
  if (total <= count) {
    for (let i = 1; i <= total; i++) {
      pages.push(i);
    }
    return pages;
  }

  // 总页数大于显示数量，需要计算显示的页码范围
  const half = Math.floor(count / 2);
  let start = current - half;
  let end = current + half;

  // 调整起始页码
  if (start < 1) {
    start = 1;
    end = count;
  }

  // 调整结束页码
  if (end > total) {
    end = total;
    start = total - count + 1;
  }

  // 生成页码列表
  for (let i = start; i <= end; i++) {
    pages.push(i);
  }

  return pages;
});

// 是否显示前省略号
const showPrevEllipsis = computed(() => {
  return pageNumbers.value.length > 0 && pageNumbers.value[0] > 1;
});

// 是否显示后省略号
const showNextEllipsis = computed(() => {
  return pageNumbers.value.length > 0 && pageNumbers.value[pageNumbers.value.length - 1] < totalPages.value;
});

// 监听页码变化，同步跳转输入框的值
watch(
  () => props.currentPage,
  (newVal) => {
    jumpPage.value = newVal;
  }
);

// 监听每页条数变化
watch(
  () => props.pageSize,
  (newVal) => {
    currentPageSize.value = newVal;
  }
);

// 处理页码变化
const handlePageChange = (page: number) => {
  if (page === props.currentPage || props.disabled) return;
  emit('update:currentPage', page);
  emit('change', page, currentPageSize.value);
};

// 处理每页条数变化
const handleSizeChange = () => {
  if (currentPageSize.value === props.pageSize || props.disabled) return;
  // 当改变每页条数时，重置到第一页
  emit('update:pageSize', currentPageSize.value);
  emit('update:currentPage', 1);
  emit('change', 1, currentPageSize.value);
};

// 上一页
const handlePrevPage = () => {
  if (props.currentPage > 1 && !props.disabled) {
    const newPage = props.currentPage - 1;
    emit('update:currentPage', newPage);
    emit('change', newPage, currentPageSize.value);
  }
};

// 下一页
const handleNextPage = () => {
  if (props.currentPage < totalPages.value && !props.disabled) {
    const newPage = props.currentPage + 1;
    emit('update:currentPage', newPage);
    emit('change', newPage, currentPageSize.value);
  }
};

// 首页
const handleFirstPage = () => {
  if (props.currentPage > 1 && !props.disabled) {
    emit('update:currentPage', 1);
    emit('change', 1, currentPageSize.value);
  }
};

// 末页
const handleLastPage = () => {
  if (props.currentPage < totalPages.value && !props.disabled) {
    emit('update:currentPage', totalPages.value);
    emit('change', totalPages.value, currentPageSize.value);
  }
};

// 处理跳转
const handleJump = () => {
  let page = jumpPage.value;
  
  // 验证页码有效性
  if (isNaN(page) || page < 1 || page > totalPages.value || props.disabled) {
    jumpPage.value = props.currentPage;
    return;
  }
  
  // 转换为整数
  page = Math.floor(page);
  
  if (page !== props.currentPage) {
    emit('update:currentPage', page);
    emit('change', page, currentPageSize.value);
  }
};

// 初始化时确保页码有效性
onMounted(() => {
  if (props.currentPage < 1 || props.currentPage > totalPages.value) {
    emit('update:currentPage', 1);
  }
});
</script>

<style lang="scss" scoped>
@use "sass:color";

// 变量定义
$border-color: #dcdfe6;
$active-bg: #f0f7ff;
$active-color: #1890ff;
$active-border: #bfdbfe;
$text-color: #606266;
$text-light: #909399;
$hover-bg: #f5f7fa;
$disabled-opacity: 0.5;

// 混合宏定义
@mixin button-base {
  width: 2rem;
  height: 2rem;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 4px;
  border: 1px solid $border-color;
  background-color: #fff;
  transition: background-color 0.2s;
  
  &:hover {
    background-color: $hover-bg;
  }
  
  &.is-disabled,
  &:disabled {
    opacity: $disabled-opacity;
    cursor: not-allowed;
    
    &:hover {
      background-color: #fff;
    }
  }
}

.pagination-container {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 0.5rem 1rem;
  font-size: 0.875rem;
  color: $text-color;
  flex-wrap: wrap;

  &.pagination-sm {
    padding: 0.25rem 1rem;
    font-size: 0.75rem;

    .pagination-btn,
    .pagination-number {
      width: 1.75rem;
      height: 1.75rem;
    }
  }

  .pagination-total {
    color: $text-light;
  }

  .pagination-size-changer {
    display: flex;
    align-items: center;
    gap: 0.5rem;

    .pagination-select {
      border: 1px solid $border-color;
      border-radius: 4px;
      padding: 0.25rem 0.5rem;
      outline: none;

      &:focus {
        outline: none;
        ring: 1px solid $active-color;
      }
    }
  }

  .pagination-nav {
    display: flex;
    align-items: center;
    gap: 0.25rem;

    .pagination-btn {
      @include button-base;
    }

    .pagination-numbers {
      display: flex;
      align-items: center;

      .pagination-ellipsis {
        width: 2rem;
        height: 2rem;
        display: flex;
        align-items: center;
        justify-content: center;
        color: $text-light;
      }

      .pagination-number {
        @include button-base;

        &.is-active {
          background-color: $active-bg;
          color: $active-color;
          border-color: $active-border;

          &:hover {
            background-color: color.adjust($active-bg, $lightness: -5%);
          }
        }
      }
    }
  }

  .pagination-jumper {
    display: flex;
    align-items: center;
    gap: 0.5rem;

    .pagination-input {
      width: 4rem;
      border: 1px solid $border-color;
      border-radius: 4px;
      padding: 0.25rem;
      text-align: center;

      &:focus {
        outline: none;
        ring: 1px solid $active-color;
      }

      &:disabled {
        opacity: $disabled-opacity;
        cursor: not-allowed;
      }

      // 隐藏数字输入框的上下箭头
      &::-webkit-outer-spin-button,
      &::-webkit-inner-spin-button {
        appearance: none;
        margin: 0;
      }

      &[type='number'] {
        appearance: textfield;
      }
    }

    .pagination-jump-btn {
      padding: 0.25rem 0.75rem;
      border: 1px solid $border-color;
      border-radius: 4px;
      background-color: #fff;
      transition: background-color 0.2s;

      &:hover {
        background-color: $hover-bg;
      }

      &:disabled {
        opacity: $disabled-opacity;
        cursor: not-allowed;

        &:hover {
          background-color: #fff;
        }
      }
    }
  }
}
</style>
